﻿using System.Collections.Generic;
using MySqlQueryToolkit.DataAccess;

namespace MySqlQueryToolkit
{
    public interface IProfileQueryRepository
    {
        ProfileQueryResult GetEntitiesFromDatabase(string query);
    }

    public class ProfileQueryRepository : Repository, IProfileQueryRepository
    {
        private readonly IUnsafeDataAccess _dataAccess;
        private readonly IDictionary<string, string> _variableNamesToProfileQueryResultMapping;

        public ProfileQueryRepository(IUnsafeDataAccess dataAccess)
        {
            _dataAccess = dataAccess;
            _variableNamesToProfileQueryResultMapping = new Dictionary<string, string>
                                                            {
                                                                {"Handler_commit", "HandlerCommit"},
                                                                {"Handler_delete", "HandlerDelete"},
                                                                {"Handler_discover", "HandlerDiscover"},
                                                                {"Handler_prepare", "HandlerPrepare"},
                                                                {"Handler_read_first", "HandlerReadFirst"},
                                                                {"Handler_read_key", "HandlerReadKey"},
                                                                {"Handler_read_last", "HandlerReadLast"},
                                                                {"Handler_read_next", "HandlerReadNext"},
                                                                {"Handler_read_prev", "HandlerReadPrev"},
                                                                {"Handler_read_rnd", "HandlerReadRnd"},
                                                                {"Handler_read_rnd_next", "HandlerReadRndNext"},
                                                                {"Handler_rollback", "HandlerRollback"},
                                                                {"Handler_savepoint", "HandlerSavepoint"},
                                                                {"Handler_savepoint_rollback", "HandlerSavepointRollback"},
                                                                {"Handler_update", "HandlerUpdate"},
                                                                {"Handler_write", "HandlerWrite"}
                                                            };
        }

        public ProfileQueryResult GetEntitiesFromDatabase(string query)
        {
            ProfileQueryResult profileQueryResult;
            using (_dataAccess)
            {
                _dataAccess.OpenConnection();
                ClearDatabaseStatus();
                ExecuteQuery(query);
                profileQueryResult = GetProfileQueryResult();
            }
            return profileQueryResult;
        }

        private ProfileQueryResult GetProfileQueryResult()
        {
            var profileQueryResult = new ProfileQueryResult();
            _dataAccess.CommandText = "SHOW SESSION STATUS LIKE 'ha%';";
            _dataAccess.ExecuteReader(reader =>
                                          {
                                              while (reader.Read())
                                              {
                                                  var variableName = reader.GetString(reader.GetOrdinal("Variable_name"));
                                                  var variableValue = reader.GetInt64(reader.GetOrdinal("Value"));
                                                  profileQueryResult.GetType().GetProperty(_variableNamesToProfileQueryResultMapping[variableName]).SetValue(profileQueryResult, variableValue, null);
                                              }
                                          });
            return profileQueryResult;
        }

        private void ExecuteQuery(string query)
        {
            _dataAccess.CommandText = query;
            _dataAccess.ExecuteNonQuery();
        }

        private void ClearDatabaseStatus()
        {
            _dataAccess.CommandText = "FLUSH STATUS;";
            _dataAccess.ExecuteNonQuery();
        }
    }
}
